package org.budo.netty.servlet.server.event;

import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.budo.netty.servlet.server.handler.servlet.BudoServletContext;

/**
 * @author lmw
 */
public class BudoEventBus implements EventBus {
    @Override
    public void contextInitialized(ServletContext servletContext) {
        ServletContextEvent event = new ServletContextEvent(servletContext);

        List<ServletContextListener> listeners = ((BudoServletContext) servletContext).listListener(ServletContextListener.class);
        for (ServletContextListener listener : listeners) {
            listener.contextInitialized(event);
        }
    }

    @Override
    public void contextDestroyed(ServletContext servletContext) {
        ServletContextEvent event = new ServletContextEvent(servletContext);

        List<ServletContextListener> listeners = ((BudoServletContext) servletContext).listListener(ServletContextListener.class);
        for (ServletContextListener listener : listeners) {
            listener.contextDestroyed(event);
        }
    }

    @Override
    public void servletContextAttributeSetted(ServletContext servletContext, String name, Object value) {
        Object previousValue = servletContext.getAttribute(name);
        ServletContextAttributeEvent event = new ServletContextAttributeEvent(servletContext, name, previousValue);

        List<ServletContextAttributeListener> listeners = ((BudoServletContext) servletContext).listListener(ServletContextAttributeListener.class);
        for (ServletContextAttributeListener listener : listeners) {

            if (null == previousValue) {
                listener.attributeAdded(event);
            } else if (null == value) {
                listener.attributeRemoved(event);
            } else {
                listener.attributeReplaced(event);
            }
        }
    }

    @Override
    public void requestInitialized(HttpServletRequest request) {
        ServletRequestEvent servletRequestEvent = new ServletRequestEvent(request.getServletContext(), request);

        BudoServletContext servletContext = (BudoServletContext) request.getServletContext();
        List<ServletRequestListener> servletRequestListeners = servletContext.listListener(ServletRequestListener.class);

        for (ServletRequestListener servletRequestListener : servletRequestListeners) {
            servletRequestListener.requestInitialized(servletRequestEvent);
        }
    }

    @Override
    public void requestDestroyed(HttpServletRequest request) {
        ServletRequestEvent servletRequestEvent = new ServletRequestEvent(request.getServletContext(), request);

        BudoServletContext servletContext = (BudoServletContext) request.getServletContext();
        List<ServletRequestListener> servletRequestListeners = servletContext.listListener(ServletRequestListener.class);

        for (ServletRequestListener servletRequestListener : servletRequestListeners) {
            servletRequestListener.requestDestroyed(servletRequestEvent);
        }
    }

    @Override
    public void sessionCreated(HttpSession session) {
        HttpSessionEvent sessionEvent = new HttpSessionEvent(session);
        BudoServletContext servletContext = (BudoServletContext) session.getServletContext();

        List<HttpSessionListener> listeners = servletContext.listListener(HttpSessionListener.class);
        for (HttpSessionListener listener : listeners) {
            listener.sessionCreated(sessionEvent);
        }
    }

    @Override
    public void sessionDestroyed(HttpSession session) {
        HttpSessionEvent sessionEvent = new HttpSessionEvent(session);
        BudoServletContext servletContext = (BudoServletContext) session.getServletContext();

        List<HttpSessionListener> listeners = servletContext.listListener(HttpSessionListener.class);
        for (HttpSessionListener listener : listeners) {
            listener.sessionDestroyed(sessionEvent);
        }
    }

    @Override
    public void sessionAttributeSetted(HttpSession session, String name, Object value) {
        Object previousValue = session.getAttribute(name);

        BudoServletContext servletContext = (BudoServletContext) session.getServletContext();
        HttpSessionBindingEvent event = new HttpSessionBindingEvent(session, name, value);

        List<HttpSessionAttributeListener> listeners = servletContext.listListener(HttpSessionAttributeListener.class);
        for (HttpSessionAttributeListener listener : listeners) {
            if (null == previousValue) {
                listener.attributeAdded(event);
            } else {
                listener.attributeReplaced(event);
            }
        }
    }

    @Override
    public void sessionAttributeRemoved(HttpSession session, String name) {
        BudoServletContext servletContext = (BudoServletContext) session.getServletContext();
        HttpSessionBindingEvent event = new HttpSessionBindingEvent(session, name);

        List<HttpSessionAttributeListener> listeners = servletContext.listListener(HttpSessionAttributeListener.class);
        for (HttpSessionAttributeListener listener : listeners) {
            listener.attributeRemoved(event);
        }
    }

    @Override
    public void requestAttributeSetted(HttpServletRequest request, String name, Object value) {
        Object previousValue = request.getAttribute(name);
        BudoServletContext servletContext = (BudoServletContext) request.getServletContext();
        ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(servletContext, request, name, value);

        List<ServletRequestAttributeListener> listeners = servletContext.listListener(ServletRequestAttributeListener.class);
        for (ServletRequestAttributeListener listener : listeners) {
            if (null == previousValue) {
                listener.attributeAdded(event);
            } else {
                listener.attributeReplaced(event);
            }
        }
    }

    @Override
    public void requestAttributeRemove(HttpServletRequest request, String name) {
        Object value = request.getAttribute(name);
        BudoServletContext servletContext = (BudoServletContext) request.getServletContext();
        ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(servletContext, request, name, value);

        List<ServletRequestAttributeListener> listeners = servletContext.listListener(ServletRequestAttributeListener.class);
        for (ServletRequestAttributeListener listener : listeners) {
            listener.attributeRemoved(event);
        }
    }
}